package auth

import (
	"context"
	"crypto/rand"
	"demo/domain/model"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"github.com/go-redis/redis/v8"
)

// 配置常量
const (
	SessionCookieName = "user-session" // Cookie 名称
	SessionPrefix     = "session:"     // Redis Key 前缀
	MaxAge            = 86400          // Session 有效期（24小时）
)

var redisClient *redis.Client

// 初始化 Redis 客户端（由业务层注入）
func InitRedis(client *redis.Client) {
	redisClient = client
}

// 生成随机 Session ID
func generateSessionID() (string, error) {
	b := make([]byte, 32)
	if _, err := rand.Read(b); err != nil {
		return "", err
	}
	return base64.URLEncoding.EncodeToString(b), nil
}

// SetSession 保存用户 Session（复用已有 ID 或生成新 ID）
func SetSession(w http.ResponseWriter, r *http.Request, user *model.UserSimple) error {
	// 尝试从 Cookie 中读取已有 Session ID
	var sessionID string
	if cookie, err := r.Cookie(SessionCookieName); err == nil {
		sessionID = cookie.Value
		// 检查 Redis 中是否存在该 Session（防止非法 ID）
		key := SessionPrefix + sessionID
		exists, err := redisClient.Exists(context.Background(), key).Result()
		if err == nil && exists > 0 {
			// 已有有效 Session，更新有效期并返回
			return redisClient.Expire(context.Background(), key, time.Duration(MaxAge)*time.Second).Err()
		}
	}

	// 无有效 Session，生成新 ID 并保存
	newSessionID, err := generateSessionID()
	if err != nil {
		return fmt.Errorf("生成 Session ID 失败: %w", err)
	}

	// 序列化用户信息
	userJSON, err := json.Marshal(user)
	if err != nil {
		return fmt.Errorf("序列化用户失败: %w", err)
	}

	// 存入 Redis
	key := SessionPrefix + newSessionID
	if err := redisClient.Set(context.Background(), key, userJSON, time.Duration(MaxAge)*time.Second).Err(); err != nil {
		return fmt.Errorf("Redis 存储失败: %w", err)
	}

	// 设置 Cookie
	http.SetCookie(w, &http.Cookie{
		Name:     SessionCookieName,
		Value:    newSessionID,
		MaxAge:   MaxAge,
		Path:     "/",
		HttpOnly: true,
		Secure:   false, // 生产环境 HTTPS 时设为 true
	})
	return nil
}

// GetCurrentUser 从 Session 获取当前用户
func GetCurrentUser(r *http.Request) (*model.UserSimple, error) {
	// 从 Cookie 读取 Session ID
	cookie, err := r.Cookie(SessionCookieName)
	if err != nil {
		return nil, fmt.Errorf("未找到 Session Cookie: %w", err)
	}
	sessionID := cookie.Value

	// 从 Redis 读取用户信息
	key := SessionPrefix + sessionID
	userJSON, err := redisClient.Get(context.Background(), key).Bytes()
	if err != nil {
		return nil, fmt.Errorf("Redis 读取失败: %w", err)
	}

	// 反序列化
	var user model.UserSimple
	if err := json.Unmarshal(userJSON, &user); err != nil {
		return nil, fmt.Errorf("反序列化失败: %w", err)
	}
	return &user, nil
}

// ClearSession 清除 Session
func ClearSession(w http.ResponseWriter, r *http.Request) error {
	// 从 Cookie 读取 Session ID
	cookie, err := r.Cookie(SessionCookieName)
	if err != nil {
		return fmt.Errorf("未找到 Session Cookie: %w", err)
	}
	sessionID := cookie.Value

	// 删除 Redis 中的 Session
	key := SessionPrefix + sessionID
	if err := redisClient.Del(context.Background(), key).Err(); err != nil {
		return fmt.Errorf("Redis 删除失败: %w", err)
	}

	// 清除 Cookie
	http.SetCookie(w, &http.Cookie{
		Name:     SessionCookieName,
		Value:    "",
		MaxAge:   -1,
		Path:     "/",
		HttpOnly: true,
	})
	return nil
}
